import React, { PureComponent } from 'react'
import { connect, withRouter } from '@umijs/max'
import { ExclamationCircleFilled } from '@ant-design/icons'
import { Form, Input, message, Modal, Radio, Select, Spin, TreeSelect } from 'antd'
import list2tree from 'list2tree'
import { defaultIconFun, HufuTreeTitle, ProTree, searchTreeListByName } from '@/components'
import { TreeIcon } from '../../../components'
import { getListAll, getTaskDetail, getTree, saveDir, saveFlinkTaskNode } from '../api'
import Tools from '@/utils/Tools'
import { regExp } from '@/utils/regExp.js'
import styles from './index.less'
import { getHashParameterByName } from '@/utils/helper'

const Bus = Tools.Bus
const { Item } = Form
const { TextArea } = Input
const { Option } = Select

const getNavTreeDataFunc = list2tree({
  idKey: 'id',
  parentIdKey: 'pid',
  newKey: {
    key: 'id',
    value: 'id',
    title: 'name',
  },
})

/**
 * 数据开发任务类型 ----------------------------nodeType-----------------------------------
 * 0：普通目录
 * 1：flinkSql
 * */
const isDir = (nodeType) => [0].includes(nodeType)
const getIcon = (nodeType, selectedKeys, themeValue) => {
  switch (nodeType) {
    case 0:
      return (props) => defaultIconFun(props, selectedKeys, themeValue)
    case 1:
      return <TreeIcon color="blue" iconName="icon-FlinkSQLrenwu"/>
    case 3:
      return <TreeIcon color="blue" iconName="icon-Flinkrenwu"/>
    default:
      return null
  }
}

// @connect(({ flowDev }) => ({ ...flowDev }))
class FlowDevTree extends PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      dirTree: [],
      modifyId: null,
      isShowTaskFlow: false,
      treeDataNew: props.treeList || [],
      allValues: {},
      operations: (item) => {
        const top = [
          <span
            key={1}
            onClick={() => this.showFilesModal(item.id)}
          >
            新建目录
          </span>,
        ]
        const footer = [
          <span
            key={5}
            onClick={() => {
              this.onDelete(item)
            }}
          >
            删除
          </span>,
        ]
        const operationsObj = {
          0: [
            ...top,
            <span
              key={2}
              onClick={() => this.showProcedureModal(item.id)}
            >
              新建实时开发
            </span>,
            <span
              key={4}
              onClick={() => this.editFilesModal(item)}
            >
              编辑
            </span>,
            ...footer,
          ],
          1: [
            <span
              key={4}
              onClick={() => this.editTaskModal(item)}
            >
              编辑
            </span>,
            ...footer,
          ],
          3: [
            <span
              key={4}
              onClick={() => this.editTaskModal(item)}
            >
              编辑
            </span>,
            ...footer,
          ],
        }[item.nodeType]
        return [
          ...(operationsObj || []),
        ]
      },
      navListSpinning: false,
    }
    this.fileForm = React.createRef()
    this.procedureFormData = React.createRef()
  }

  componentDidMount() {
    this.getResourceListAll()
    const tempTaskId = getHashParameterByName('taskId')
    this.getListAll(() => this.onSelectTask([tempTaskId]))
    this.getDirTree()
    Bus.addListener('ShowProcedureModal', this.showProcedureModal)
    Bus.addListener('getListAll', this.getListAll)
  }

  UNSAFE_componentWillReceiveProps(nextProps) {
    if (nextProps.treeList != this.props.treeList) {
      this.setState({
        treeDataNew: nextProps.treeList,
      }, () => {
        const queryNodeId = getHashParameterByName('nodeId')
        const queryNodeName = getHashParameterByName('nodeName')
        if (queryNodeId) {
          setTimeout(() => {
            this.onSelectTask([queryNodeId])
            const searchTree = searchTreeListByName(
              queryNodeName,
              this.props?.navList,
            )
            this.tree.onExpand(searchTree.fatchIds)
          })
        }
      })
    }
  }

  componentWillUnmount() {
    Bus.removeListener('ShowProcedureModal', this.showProcedureModal)
    Bus.removeListener('getListAll', this.getListAll)
  }

  editTaskModal = (item) => {
    this.setState({
      modifyId: item.id,
      isShowTaskFlow: true,
    }, () => {
      getTaskDetail({ nodeId: item.id }).then((res) => {
        if (res.status == 200 && res.data) {
          this.procedureFormData?.current?.setFieldsValue({
            pid: res.data.pid == '1' ? undefined : res.data.pid,
            devType: 1,
            name: res.data.name,
            resourceNodeId: res.data.resourceNodeId,
            mainClass: res.data.mainClass,
            remark: res.data.remark,
            nodeType: res.data.nodeType,
          })
          this.setState({
            allValues: {
              nodeType: res.data.nodeType,
            },
          })
        }
      })
    })
  }

  // 获取子节点所在的工作流的id
  getTaskFlowId = (itemId) => {
    const { navList } = this.props
    const getPitem = (id) => {
      const tepObj = navList.find((item) => id == item.id)
      if (tepObj) {
        if (tepObj.nodeType == 1) {
          return tepObj.id
        }
        return getPitem(tepObj.pid)
      }
      return null
    }
    return getPitem(itemId)
  }

  // 工作流弹窗
  showProcedureModal = (id) => {
    this.procedureFormData.current?.resetFields()
    this.setState({
      isShowTaskFlow: true,
      modifyId: null,
      allValues: {},
    }, () => {
      if (id) {
        this.procedureFormData.current.setFieldsValue({ pid: id })
      }
    })
  }

  // 打开新建目录弹窗
  showFilesModal = (id) => {
    this.fileForm.current?.resetFields()
    this.setState({
      modifyId: null,
      isShowFiles: true,
    }, () => {
      if (id) {
        this.fileForm.current.setFieldsValue({ pid: id })
      }
    })
    this.getDirTree()
  }

  // 编辑打开新建目录弹窗
  editFilesModal = (item) => {
    this.fileForm.current?.resetFields()
    this.setState({
      modifyId: item.id,
      isShowFiles: true,
    }, () => {
      if (item) {
        this.fileForm.current.setFieldsValue({
          pid: item.pid == '1' ? undefined : item.pid,
          name: item.name,
        })
      }
    })
    this.getDirTree()
  }

  getListAll = (cb) => {
    this.setState({
      navListSpinning: true,
    })
    this.props.dispatch({
      type: 'realTimeScriptDev/getTree',
      params: { type: 0 },
      cb: (data) => {
        this.setState({
          navListSpinning: false,
        }, () => {
          cb && cb()
        })
      },
    })
  }

  getDirTree = () => {
    this.setState({ navListSpinning: true })
    getTree({ type: 0 }).then((res) => {
      if (res.data && res.data[0]) {
        const { childs } = res.data[0]
        this.setState({
          dirTree: childs,
          navListSpinning: false,
        })
      } else {
        this.setState({
          dirTree: [],
          navListSpinning: false,
        })
      }
    }, (error) => {
      this.setState({ navListSpinning: false })
    })
  }

  fileTaskFlow = () => {
    this.procedureFormData.current.validateFields().then(values => {
      const postObj = {
        ...values,
        pid: values.pid ? values.pid : 1,
        nodeId: this.state.modifyId,
      } || {}
      saveFlinkTaskNode(postObj).then((res) => {
        if (res.status == 200) {
          const { tasks } = JSON.parse(JSON.stringify(this.props))
          // 同时打开多个task时，判断哪个task是被修改了name
          const task = tasks.find((value) => value.id == postObj.nodeId)
          if (task) {
            task.name = values.name
            // 将修改保存至props
            this.props.dispatch({
              type: 'realTimeScriptDev/upFlow',
              params: {
                tasks,
              },
            })
          }
          this.setState({
            isShowTaskFlow: false,
          })
          this.getListAll()
          message.success(res.msg)
        } else {
          message.warning(res.msg)
        }
      })
    })
  }

  // 删除回调
  onDelete = (item) => {
    Modal.confirm({
      title: '确认要删除吗？',
      icon: <ExclamationCircleFilled/>,
      content: '删除后数据将无法恢复，请谨慎操作',
      okText: '删除',
      cancelText: '取消',
      okButtonProps: {
        danger: true,
      },
      onOk: () => {
        this.props.dispatch({
          type: 'realTimeScriptDev/deleteNode',
          params: { id: item.id, taskFlowId: this.getTaskFlowId(item.pid) },
          cb: (res) => {
            if (res.status == 200) {
              this.getListAll()
              message.success(res.msg)
              Bus.emit('refreshFlow')
              if ([1].includes(item.nodeType)) {
                this.props.dispatch({
                  type: 'realTimeScriptDev/deleteTaskId',
                  params: {
                    id: item.id,
                  },
                })
              }
            } else {
              message.error(res.msg)
            }
          },
        })
      },
    })
  }

  renderTreeNodes = (data) => {
    const { operations } = this.state
    const { taskId, themeValue } = this.props
    const tempArr = []
    data.map((item) => {
      const {
        name, id, nodeType,
      } = item
      const icon = getIcon(nodeType, taskId ? [taskId] : [], themeValue)
      const tempObj = {
        icon,
        key: id,
        nodeType,
        item: {
          id: item.id,
          title: item.title,
          nodeType,
        },
        selectable: [0, 1, 3].includes(nodeType),
      }
      if (item.pid != '0') {
        tempObj.title = (
          <HufuTreeTitle
            title={name}
            key={item.id}
            icon
            operations={operations(item)}
          />
        )
      } else {
        tempObj.title = (
          <HufuTreeTitle
            title={name}
            key={item.id}
            icon
            operations={[
              <span
                key={6}
                onClick={() => this.showModal(item.id)}
              >
                新建分组
              </span>,
            ]}
          />
        )
      }
      if (item.children) {
        tempObj.children = this.renderTreeNodes(item.children)
      }
      tempArr.push(tempObj)
    })
    return tempArr
  }

  onSelectTask = (selectedKeys, e) => {
    const targetKey = selectedKeys[0]
    const item = this.getTask(targetKey)
    if (item && !isDir(item.nodeType)) {
      this.props.dispatch({
        type: 'realTimeScriptDev/taskTabsHandle',
        params: {
          id: targetKey,
          item,
        },
      })
    }
    this.props.dispatch({
      type: 'realTimeScriptDev/setSelectedKey',
      params: {
        selectedKeys: targetKey,
        treeCurrentTargetNode: item,
      },
      cb: () => {
        Bus.emit('editorLayout', targetKey)
      },
    })
  }

  // 根据id找到任务对象
  getTask = (id) => {
    const { navList } = this.props
    return navList.find((item) => id == item.id)
  }

  // 新建目录确认
  filesOnOk = () => {
    this.fileForm.current.validateFields().then(values => {
      this.setState({ navListSpinning: true })
      if (this.state.modifyId) {
        values.id = this.state.modifyId
      }
      if (!values.pid) values.pid = 1
      saveDir({ ...values, nodeType: 0, type: 0 }).then(
        (res) => {
          message.success(this.state.modifyId ? '修改目录成功' : '新建目录成功')
          this.setState({
            isShowFiles: false,
            navListSpinning: false,
          }, () => {
            this.getListAll()
            this.getDirTree()
          })
        },
        (error) => {
          this.setState({ navListSpinning: false })
          console.log(error)
        },
      )
    })
  }

  valuesChange = (value, allValues) => {
    this.setState({
      allValues,
    })
  }

  getResourceListAll = () => {
    getListAll({ type: 1, resourceFlag: 0 }).then((res) => {
      if (res.status == 200) {
        this.setState({
          resources: res.data,
        })
      }
    })
  }

  render() {
    const { title, taskId } = this.props
    const { allValues, resources } = this.state
    const descRe = regExp.proName(0, 128)
    return (
      <div
        className={`${styles.script_dev}`}
      >
        <Spin spinning={this.state.navListSpinning}>
          <div className={styles.datadev_tree_box}>
            <ProTree
              selectedKeys={taskId ? [taskId] : []}
              showSearch
              onSelect={this.onSelectTask}
              title={title || '目录'}
              operations={[
                <i
                  key="0"
                  className="iconfont icon-shuaxin"
                  title="刷新"
                  onClick={() => {
                    this.getListAll()
                    this.getDirTree()
                  }}
                />,
                <i
                  key="1"
                  className="iconfont icon-xinjianwenjianjia"
                  title="新建文件夹"
                  onClick={() => this.showFilesModal()}
                />,
                <i
                  key="2"
                  className="iconfont icon-tianjia"
                  title="新建实时开发"
                  onClick={() => this.showProcedureModal()}
                />,
              ]}
              treeData={this.state.treeDataNew}
              renderTreeNodes={this.renderTreeNodes}
              ref={(dev) => (this.tree = dev)}
              search={(name) => {
                const searchTree = searchTreeListByName(
                  name,
                  this.props.navList,
                )
                const treeDataNew = getNavTreeDataFunc(
                  searchTree.result,
                )
                this.setState(
                  {
                    treeDataNew,
                  },
                  () => {
                    this.tree.onExpand(searchTree.fatchIds)
                  },
                )
              }}
            />
          </div>
        </Spin>
        <Modal
          title={this.state.modifyId ? '修改目录' : '新建目录'}
          visible={this.state.isShowFiles}
          confirmLoading={this.state.navListSpinning}
          cancelText="取消"
          okText="保存"
          onOk={this.filesOnOk}
          onCancel={() => {
            this.setState({
              isShowFiles: false,
            })
          }}
          maskClosable={false}
        >
          <div className={styles.file_box}>
            <Form
              ref={this.fileForm}
              labelCol={{ span: 5 }}
              wrapperCol={{ span: 19 }}
              autoComplete="off"
            >
              <Item
                label="目录名称"
                name="name"
                rules={[
                  { required: true, message: '请输入目录名称' },
                ]}
              >
                <Input placeholder="请输入目录名称"/>
              </Item>
              <Item
                label="父级目录"
                name="pid"
              >
                <TreeSelect
                  allowClear
                  showSearch
                  getPopupContainer={(triggerNode) => triggerNode.parentNode}
                  // dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                  treeData={this.state.dirTree || []}
                  placeholder="请选择父级目录"
                  treeDefaultExpandAll
                  filterTreeNode={(input, treeNode) => treeNode.name.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  fieldNames={{
                    label: 'name', value: 'id', children: 'childs',
                  }}
                />
              </Item>
            </Form>
          </div>
        </Modal>
        <Modal
          width={600}
          title={this.state.modifyId ? '修改实时开发' : '创建实时开发'}
          visible={this.state.isShowTaskFlow}
          confirmLoading={this.state.confirmLoading}
          cancelText="取消"
          okText="保存"
          onOk={this.fileTaskFlow}
          onCancel={() => {
            this.setState({
              isShowTaskFlow: false,
            })
          }}
        >
          <div className={styles.file_box}>
            <Form
              labelCol={{ span: 5 }}
              wrapperCol={{ span: 19 }}
              autoComplete="off"
              ref={this.procedureFormData}
              onValuesChange={this.valuesChange}
              initialValues={{
                devType: 1,
                nodeType: 1,
              }}
            >
              <Form.Item
                label="开发模式"
                name="devType"
                rules={[
                  { required: true, message: '请选择开发模式' },
                ]}
              >
                <Radio.Group disabled={!!this.state.modifyId}>
                  <Radio value={1}>脚本模式</Radio>
                  <Radio disabled value={2}>向导模式</Radio>
                </Radio.Group>
              </Form.Item>
              <Form.Item
                label="任务名称"
                name="name"
                rules={[
                  { required: true, message: '请输入任务名称' },
                  {
                    required: false,
                    pattern: new RegExp(regExp.name(2, 64).reg, 'g'),
                    message: regExp.name(2, 64).text,
                  },
                ]}
              >
                <Input placeholder="请输入工作流程名称"/>
              </Form.Item>
              <Form.Item
                label="任务类型"
                name="nodeType"
                rules={[
                  { required: true, message: '请选择任务类型' },
                ]}
              >
                <Radio.Group disabled={!!this.state.modifyId}>
                  <Radio value={1}>FlinkSQL</Radio>
                  <Radio value={3}>Flink</Radio>
                </Radio.Group>
              </Form.Item>
              {allValues.nodeType == 3 ? (
                <Form.Item
                  label="资源"
                  name="resourceNodeId"
                  rules={[
                    { required: true, message: '请选择资源' },
                  ]}
                >
                  <Select placeholder="请选择资源">
                    {resources && resources.map((item) => <Option key={item.id} value={item.id}>{item.name}</Option>)}
                  </Select>
                </Form.Item>
              ) : null}
              {allValues.nodeType == 3 ? (
                <Form.Item
                  label="mainClass"
                  name="mainClass"
                  rules={[
                    { required: true, message: '请输入mainClass' },
                  ]}
                >
                  <Input placeholder="请输入mainClass"/>
                </Form.Item>
              ) : null}
              <Form.Item
                label="父级目录"
                name="pid"
              >
                <TreeSelect
                  treeData={this.state.dirTree || []}
                  dropdownStyle={{ maxHeight: '4rem', overflow: 'auto' }}
                  placeholder="选择父级目录"
                  allowClear
                  fieldNames={
                    {
                      label: 'name',
                      value: 'id',
                      children: 'childs',
                    }
                  }
                  filterTreeNode={(input, treeNode) => treeNode.name.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  showSearch
                  treeDefaultExpandAll
                />
              </Form.Item>
              <Form.Item
                label="描述"
                name="remark"
                rules={[
                  { required: false },
                  {
                    pattern: new RegExp(descRe.reg, 'g'),
                    message: descRe.text,
                  },
                ]}
              >
                <TextArea
                  placeholder="请输入实时计算的业务描述"
                  autoSize={{ minRows: 3, maxRows: 6 }}
                />
              </Form.Item>
            </Form>
          </div>
        </Modal>
      </div>
    )
  }
}

export default connect(({
                          global,
                          realTimeScriptDev
                        }) => ({ themeValue: global.themeValue, ...realTimeScriptDev }))(withRouter(FlowDevTree))
